package com.orgcent.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.Drawable;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.StatFs;
import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

/**
 * 工具包
 */
public final class Tools {
	/**
	 * 获取当前IP地址（判断手机是否联网的方法）
	 * 
	 * @return
	 */
	public static String getLocalIpAddress() {
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface
					.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf
						.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress()) {
						return inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (SocketException ex) {
			ex.printStackTrace();
		}
		return null;
	}

	/**
	 * URL 正则表达式
	 */
	public static final String URL_PATTERN = "^((https|http|ftp|rtsp|mms)?://)"
			+ "?(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?" // ftp的user@
			+ "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP形式的URL- 199.194.52.184
			+ "|" // 允许IP和DOMAIN（域名）
			+ "([0-9a-zA-Z_!~*'()-]+\\.)*" // 域名- www.
			+ "([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z]\\." // 二级域名
			+ "[a-zA-Z]{2,6})" // first level domain- .com or .museum
			+ "(:[0-9]{1,4})?" // 端口- :80
			+ "((/?)|" + "(/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+/?)$";

	public static boolean isURL(String url) {
		return (null != url) && url.matches(URL_PATTERN);
	}

	/**
	 * 获取域名指向的IP
	 * 
	 * @param uri
	 *            如：www.google.com
	 * @return
	 */
	public static String getDNSIP(String uri) {
		try {
			InetAddress[] addresses = InetAddress.getAllByName(uri);
			if (null != addresses) {
				return addresses[0].getHostAddress();
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 图片工具包
	 * 
	 */
	public static final class Image {

		/**
		 * 获得圆角图片
		 * 
		 * @param bitmap
		 * @param roundPx
		 * @return
		 */
		public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {

			Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
					.getHeight(), Config.ARGB_8888);
			Canvas canvas = new Canvas(output);

			final int color = 0xff424242;
			final Paint paint = new Paint();
			final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap
					.getHeight());
			final RectF rectF = new RectF(rect);

			paint.setAntiAlias(true);
			canvas.drawARGB(0, 0, 0, 0);
			paint.setColor(color);
			canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

			paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
			canvas.drawBitmap(bitmap, rect, rect, paint);

			return output;
		}

		/**
		 * 获得带倒影的图片
		 * 
		 * @param bitmap
		 * @return
		 */
		public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
			final int reflectionGap = 4;
			int width = bitmap.getWidth();
			int height = bitmap.getHeight();

			Matrix matrix = new Matrix();
			matrix.preScale(1, -1);

			Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,
					width, height / 2, matrix, false);

			Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
					(height + height / 2), Config.ARGB_8888);

			Canvas canvas = new Canvas(bitmapWithReflection);
			canvas.drawBitmap(bitmap, 0, 0, null);
			Paint deafalutPaint = new Paint();
			canvas.drawRect(0, height, width, height + reflectionGap,
					deafalutPaint);

			canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);

			Paint paint = new Paint();
			LinearGradient shader = new LinearGradient(0, bitmap.getHeight(),
					0, bitmapWithReflection.getHeight() + reflectionGap,
					0x70ffffff, 0x00ffffff, TileMode.CLAMP);
			paint.setShader(shader);
			// Set the Transfer mode to be porter duff and destination in
			paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
			// Draw a rectangle using the paint with our linear gradient
			canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
					+ reflectionGap, paint);

			return bitmapWithReflection;
		}

		/**
		 * 放大缩小图片,可以指定宽度和高度
		 * 
		 * @param bitmap
		 * @param w
		 * @param h
		 * @return
		 */
		public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
			int width = bitmap.getWidth();
			int height = bitmap.getHeight();
			Matrix matrix = new Matrix();
			float scaleWidht = ((float) w / width);
			float scaleHeight = ((float) h / height);
			matrix.postScale(scaleWidht, scaleHeight);
			Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height,
					matrix, true);
			return newbmp;
		}

		/**
		 * 将bitmap对象转换为字节
		 * 
		 * @param bitmap
		 *            源图片
		 * @param fmt
		 *            要压缩的格式,jpg/png ...
		 * @return
		 */
		public static byte[] bitmapToByte(Bitmap bitmap, CompressFormat fmt) {
			final ByteArrayOutputStream baos = new ByteArrayOutputStream();
			bitmap.compress(fmt, 100, baos);
			return baos.toByteArray();
		}

		/**
		 * 将Drawable对象转换为字节
		 * 
		 * @param image
		 * @param fmt
		 * @return
		 */
		public static byte[] bitmapToByte(Drawable image, CompressFormat fmt) {
			return bitmapToByte(drawableToBitmap(image), fmt);
		}

		/**
		 * 将Drawable转换为Bitmap对象
		 * 
		 * @param drawable
		 * @return
		 */
		public static Bitmap drawableToBitmap(Drawable drawable) {
			final Bitmap bitmap = Bitmap
					.createBitmap(
							drawable.getIntrinsicWidth(),
							drawable.getIntrinsicHeight(),
							drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
									: Bitmap.Config.RGB_565);
			Canvas canvas = new Canvas(bitmap);
			drawable.draw(canvas);
			canvas = null;
			return bitmap;
		}

		/**
		 * 在图片打水印
		 * 
		 * @param src
		 *            原始位图
		 * @param text
		 *            水印文字
		 * @param x
		 *            水印x坐标
		 * @param y
		 *            水印y坐标
		 * @param paint
		 *            带指定样式的画笔
		 * @return 返回一个新的位图对象
		 */
		public static Bitmap createBitmap(Bitmap src, String text, float x,
				float y, Paint paint) {
			if (src == null) {
				return null;
			}
			final Bitmap newb = Bitmap.createBitmap(src);// 创建一个新的和SRC长度宽度一样的位图
			Canvas cv = new Canvas(newb);
			cv.drawText(text, x, y, paint);
			cv.save(Canvas.ALL_SAVE_FLAG);// 保存
			cv.restore();// 存储
			cv = null;
			return newb;
		}

		/**
		 * 旋转图片
		 * 
		 * @param bmp
		 *            应用旋转的图片
		 * @param degrees
		 *            要旋转的度数
		 * @return 返回旋转后的图片(Bitmap)对象
		 */
		public static Bitmap rotate(Bitmap bmp, float degrees) {
			if (null == bmp)
				return bmp;
			Matrix m = new Matrix();
			m.postRotate(degrees);
			return applyMatrix(bmp, m);
		}

		/**
		 * 将Matrix应用到Bitmap上
		 * 
		 * @param bmp
		 *            应用Matrix的图片
		 * @param m
		 * @return
		 */
		public static Bitmap applyMatrix(Bitmap bmp, Matrix m) {
			return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp
					.getHeight(), m, true);
		}

		/**
		 * 按比例缩放图片
		 * 
		 * @param bmp
		 *            原始图片
		 * @param scale
		 *            要缩放的比例，缩小(0<scale<1),放大(1<scale)无上限
		 * @return 缩放后的Bitmap图片对象
		 */
		public static Bitmap zoom(Bitmap bmp, float scale) {
			return zoom(null, bmp, scale);
		}

		/**
		 * 按比例缩放图片,若context不为空判断缩放比例是否超出屏幕大小，超出只显示屏幕大小
		 * 
		 * @param context
		 *            上下文对象，用于获取屏幕大小
		 * @param bmp
		 *            原始图片
		 * @param scale
		 *            要缩放的比例，缩小(0<scale<1),最大为屏幕大小
		 * @return 缩放后的Bitmap图片对象
		 */
		public static Bitmap zoom(Context context, Bitmap bmp, float scale) {
			if (null == bmp)
				return bmp;

			float scaledWidth = scale;
			float scaledHeight = scale;

			if (null != context) { // 判断比例是否超出屏幕，超出则设置为屏幕大小
				/**
				 * 屏幕宽度：screenWidth
				 * 缩放后的宽度(zoomWidth)等于图片当前宽度(bmp.getWidth())乘以缩放比例(scale)
				 * 若screenWidth <
				 * zoomWidth,缩放比例(scale)等于屏幕宽度(screenWidth)除以图片当前宽度
				 * (bmp.getWidth()) 否则缩放比例(scale)不需修改
				 */
				DisplayMetrics dm = getScreenSize(context);
				scaledWidth = dm.widthPixels < bmp.getWidth() * scale ? dm.widthPixels
						* 1.0F / bmp.getWidth()
						: scale;
				scaledHeight = dm.heightPixels < bmp.getHeight() * scale ? dm.heightPixels
						* 1.0F / bmp.getHeight()
						: scale;
				dm = null;
			}

			Matrix m = new Matrix();
			m.postScale(scaledWidth, scaledHeight);
			return applyMatrix(bmp, m);
		}
	}

	/**
	 * 获取整个屏幕大小
	 * 
	 * @param context
	 *            上下文对象(通常指Activity)
	 * @return 返回一个DisplayMetrics对象
	 */
	public static DisplayMetrics getScreenSize(Context context) {
		WindowManager wm = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics dm = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(dm);
		return dm;
	}

	/**
	 * <p style='color:blue;'>
	 * 必须在界面创建完成后才能调用，否则数据不正确。 建议在getWindow().getDecorView().post(new
	 * Runnable(){})中的线程run方法中的调用。
	 * <p/>
	 * 区域详解： <br/>
	 * 区域一： 指整个屏幕大小. 调用方法: {@link #getScreenSize(Context)}<br/>
	 * 区域二： 指除系统状态栏外的其他屏幕区域. 调用方法: {@link #getAppSize(Activity)} <br/>
	 * 区域三： 指除系统状态栏和程序标题栏外的其他屏幕区域. 调用方法: {@link #getAppContentSize(Activity)}<br/>
	 * 
	 * 获取内容区域大小 (区域三)
	 * 
	 * @param context
	 *            当前上下文
	 * @return 返回一个包含宽度和高度的LayoutParams对象
	 */
	public static LayoutParams getAppContentSize(Activity context) {
		View root = getDisplayRootView(context);
		return new LayoutParams(root.getWidth(), root.getHeight());
	}

	/**
	 * <p style='color:blue;'>
	 * 必须在界面创建完成后才能调用，否则数据不正确。 建议在getWindow().getDecorView().post(new
	 * Runnable(){})中的线程run方法中的调用。
	 * <p/>
	 * 区域详解： <br/>
	 * 区域一： 指整个屏幕大小. 调用方法: {@link #getScreenSize(Context)}<br/>
	 * 区域二： 指除系统状态栏外的其他屏幕区域. 调用方法: {@link #getAppSize(Activity)} <br/>
	 * 区域三： 指除系统状态栏和程序标题栏外的其他屏幕区域. 调用方法: {@link #getAppContentSize(Activity)}<br/>
	 * 
	 * 获取区域二大小
	 * 
	 * @param context
	 *            当前上下文
	 * @return 返回一个包含宽度和高度的LayoutParams对象
	 */
	public static LayoutParams getAppSize(Activity context) {
		Rect outrect = new Rect();
		getDisplayRootView(context).getWindowVisibleDisplayFrame(outrect);
		return new LayoutParams(outrect.width(), outrect.height());
	}

	/**
	 * <p style='color:blue;'>
	 * 必须在界面创建完成后才能调用，否则数据不正确。 建议在getWindow().getDecorView().post(new
	 * Runnable(){})中的线程run方法中的调用。
	 * <p/>
	 * 获取状态栏高度
	 * 
	 * @param context
	 *            当前上下文
	 * @return
	 */
	public static int getStatusBarHeight(Activity context) {
		Rect outrect = new Rect();
		getDisplayRootView(context).getWindowVisibleDisplayFrame(outrect);
		return outrect.top;
	}

	/**
	 * <p style='color:blue;'>
	 * 必须在界面创建完成后才能调用，否则数据不正确。 建议在getWindow().getDecorView().post(new
	 * Runnable(){})中的线程run方法中的调用。
	 * <p/>
	 * 获取标题栏高度
	 * 
	 * @param context
	 *            当前上下文
	 * @return
	 */
	public static int getTitleBarHeight(Activity context) {
		View layout = getDisplayRootView(context);
		Rect outrect = new Rect();
		layout.getWindowVisibleDisplayFrame(outrect);
		return outrect.height() - layout.getHeight();
	}

	/**
	 * 区域详解： <br/>
	 * 区域一： 指整个屏幕大小. 调用方法: {@link #getScreenSize(Context)}<br/>
	 * 区域二： 指除系统状态栏外的其他屏幕区域. 调用方法: {@link #getAppSize(Activity)} <br/>
	 * 区域三： 指除系统状态栏和程序标题栏外的其他屏幕区域. 调用方法: {@link #getAppContentSize(Activity)}<br/>
	 * 
	 * 获取系统当前显示的根View(区域三)
	 * 
	 * @param context
	 *            当前上下文
	 * @return 返回一个View对象，实际为一个FrameLayout对象
	 */
	public static View getDisplayRootView(Activity context) {
		return context.getWindow().findViewById(Window.ID_ANDROID_CONTENT);
	}

	/**
	 * 在Toast上显示文本信息
	 * 
	 * @param context
	 *            当前Activity
	 * @param text
	 *            要显示的信息
	 */
	public static void toastShow(Context context, String text) {
		Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
	}

	/**
	 * 提示对话框(和javascript中的alert()相似)
	 * 
	 * @param context
	 *            当前上下文(activity)
	 * @param title
	 *            提示框标题
	 * @param content
	 *            提示框内容
	 * @param positiveStr
	 *            左边按钮的名称
	 * @param negativeStr
	 *            右边按钮的名称
	 * @param listener
	 *            按钮单击事件的监听器
	 */
	public static void alert(Context context, String title, String content,
			CharSequence positiveStr, CharSequence negativeStr,
			OnClickListener listener) {
		new AlertDialog.Builder(context).setTitle(title).setMessage(content)
				.setPositiveButton(positiveStr, listener).setNegativeButton(
						negativeStr, listener).show();
	}

	/**
	 * 将Date转换为指定格式的字符串
	 * 
	 * @param d
	 *            要转换的Date对象
	 * @param format
	 *            转换格式，如：yyyy-MM-dd HH:mm:ss
	 * @return 返回指定格式的日期字符串
	 */
	public static String date2str(Date d, String format) {
		return new SimpleDateFormat(format).format(d);
	}

	/**
	 * 将Date转换为格式(yyyy-MM-dd HH:mm:ss)的字符串
	 * 
	 * @param d
	 *            要转换的Date对象
	 * @return 返回指定格式的日期字符串
	 */
	public static String date2str(Date d) {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d);
	}

	/**
	 * 验证字符串是否匹配格式
	 * 
	 * @param src
	 *            要验证的字符串
	 * @param pattern
	 *            要匹配的格式
	 * @return 匹配返回true
	 */
	public static boolean matches(String src, String pattern) {
		return null == src ? false : src.matches(pattern);
	}

	/**
	 * 根据xml中的资源Id获取View对象
	 * 
	 * @param <T>
	 * @param context
	 * @param viewResourceId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T findViewById(Activity context, int viewResourceId) {
		return null == context ? null : (T) context
				.findViewById(viewResourceId);
	}

	/**
	 * 根据xml中的资源Id获取View对象
	 * 
	 * @param <T>
	 * @param view
	 *            特定的View视图中
	 * @param viewResourceId
	 *            在View中的某个资源Id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T findViewById(View view, int viewResourceId) {
		return null == view ? null : (T) view.findViewById(viewResourceId);
	}

	/**
	 * 调用振动服务,实现振动功能
	 * 
	 * @param context
	 *            当前上下文activity
	 * @param repeat
	 *            设置从哪个位置开始重复执行模式，-1表示不重复
	 * @param pattern
	 *            一个整型数组，每个元素代表时间(单位:毫秒)
	 * @return
	 */
	public static Vibrator vibrate(Context context, int repeat, long... pattern) {
		Vibrator vbr = (Vibrator) context
				.getSystemService(Service.VIBRATOR_SERVICE);
		vbr.vibrate(pattern, repeat);
		return vbr;
	}

	/**
	 * 获取NotificationManager对象
	 * 
	 * @param context
	 * @return
	 */
	public static NotificationManager getNotificationManager(Context context) {
		return (NotificationManager) context
				.getSystemService(Service.NOTIFICATION_SERVICE);
	}

	/**
	 * 获取文件的MIME类型
	 * 
	 * @param file
	 *            需要获取类型的文件
	 * @return
	 */
	public static String getFileMIMETYPE(File file) {
		/**
		 * 方式1： InputStream is = new BufferedInputStream(new
		 * FileInputStream(file)); mimeType =
		 * URLConnection.guessContentTypeFromStream(is); 方式2(需要jdk6支持)： new
		 * MimetypesFileTypeMap().getContentType(file)
		 */
		String mimeType = null;
		try {
			mimeType = URLConnection
					.guessContentTypeFromStream(new BufferedInputStream(
							new FileInputStream(file)));
		} catch (Exception e) {
			// throw new RuntimeException(e);
		}
		return mimeType;
	}

	/**
	 * 获取系统Wifi服务管理对象
	 * 
	 * @param context
	 * @return
	 */
	public static WifiManager getWifiManager(Context context) {
		return getSystemService(context, Service.WIFI_SERVICE);
	}

	/**
	 * 获取系统Wifi服务管理对象
	 * 
	 * @param context
	 * @return
	 */
	public static TelephonyManager getTelephonyManager(Context context) {
		return getSystemService(context, Service.TELEPHONY_SERVICE);
	}

	/**
	 * 获取ActivityManager对象
	 * 
	 * @param context
	 * @return
	 */
	public static ActivityManager getActivityManager(Context context) {
		return getSystemService(context, Service.ACTIVITY_SERVICE);
	}

	/**
	 * 获取系统服务管理对象
	 * 
	 * @param <T>
	 *            要强制转换的类型
	 * @param context
	 *            当前上下文
	 * @param service
	 *            服务名称
	 * @return
	 */
	public static <T> T getSystemService(Context context, String service) {
		return (T) context.getSystemService(service);
	}

	/**
	 * 判断字符串是否为null或“”
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNull(String str) {
		return null == str || "".equals(str.trim());
	}

	/**
	 * 获取String类型的值，若参数为null或“”,返回默认值
	 * 
	 * @param value
	 * @param defValue
	 *            要返回的默认值
	 * @return
	 */
	public static String getValue(String value, String defValue) {
		return isNull(value) ? defValue : value;
	}

	/**
	 * 获取SDCard的状态
	 * 
	 * @return
	 */
	public static StatFs getSDCardStat() {
		File sdcard = Environment.getExternalStorageDirectory();
		return null == sdcard ? null : new StatFs(sdcard.getPath());
	}

	/**
	 * 设置全屏
	 * 
	 * @param context
	 */
	public static void setFullScreen(Activity context) {
		context.requestWindowFeature(Window.FEATURE_NO_TITLE);
		context.getWindow().setFlags(
				WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		/**
		 * 方法2: getWindow().setFormat(PixelFormat.TRANSLUCENT); //全屏
		 */
	}

	/**
	 * 隐藏控件上弹出的输入法对话框
	 * 
	 * @param context
	 *            当前上下文
	 * @param viewHideIME
	 *            需隐藏IME的控件
	 */
	public static void hideIMEDialog(Context context, View viewHideIME) {
		InputMethodManager im = getSystemService(context,
				Service.INPUT_METHOD_SERVICE);
		im.hideSoftInputFromWindow(viewHideIME.getWindowToken(), 0);
	}
}
